markdown-text-editor 1.8.0 → 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -4
- package/dist/markdown-text-editor.es.js +129 -81
- package/dist/markdown-text-editor.es.js.map +1 -1
- package/dist/markdown-text-editor.min.js +11 -11
- package/dist/markdown-text-editor.min.js.map +1 -1
- package/dist/markdown-text-editor.umd.js +11 -11
- package/dist/markdown-text-editor.umd.js.map +1 -1
- package/package.json +3 -2
- package/types/index.d.ts +93 -1
package/README.md
CHANGED
|
@@ -40,7 +40,7 @@ Most JavaScript markdown editors (EasyMDE, SimpleMDE, CodeMirror-based editors)
|
|
|
40
40
|
| Swap the markdown parser | ✅ | ❌ |
|
|
41
41
|
| Keyboard shortcuts | ✅ | Partial |
|
|
42
42
|
| Dark mode / theming | ✅ | Limited |
|
|
43
|
-
| Bundle size, gzipped |
|
|
43
|
+
| Bundle size, gzipped | 54 KB | 107 KB (JS + CSS) |
|
|
44
44
|
|
|
45
45
|
## 🚀 Quick Start
|
|
46
46
|
|
|
@@ -96,13 +96,14 @@ That's it. Form submission, `.value` access, and all native textarea behaviour w
|
|
|
96
96
|
- 🔄 **Undo / Redo** — Full diff-based history with exact cursor restoration. Works with `Ctrl+Z`, `Ctrl+Y`, `Ctrl+Shift+Z`
|
|
97
97
|
- ♿ **Accessible by Default** — `role="toolbar"`, `aria-pressed`, `aria-disabled`, `disabled`, screen-reader-friendly SVGs, and correct focus restoration on modal close
|
|
98
98
|
- 🛡️ **XSS Safe** — Preview output sanitized via [DOMPurify](https://github.com/cure53/DOMPurify) before rendering, including the output of a custom renderer
|
|
99
|
-
- 🛡️ **
|
|
99
|
+
- 🛡️ **No inline scripts** — No inline event handlers and no `eval`, so `script-src` needs no exception. The stylesheet is currently injected as a `<style>` element, which a strict `style-src` blocks ([#42](https://github.com/nezanuha/markdown-text-editor/issues/42))
|
|
100
100
|
- 🌍 **RTL Support** — Native Right-to-Left support for Arabic, Urdu, Farsi, and other RTL languages
|
|
101
101
|
- 🌙 **Dark Mode & Theming** — Inherits `data-theme` from any ancestor element. Built-in light, dark, snowberry, and darkberry themes. Fully customizable via CSS variables
|
|
102
|
+
- 🧩 **Custom Tools** — Add your own toolbar button with `{ custom: { title, icon, action } }`, or extend `MarkdownEditor.Tool` when it builds its own markup. Keyboard shortcuts, translation and teardown work exactly as they do for the built-ins. No fork, no patching
|
|
102
103
|
- 🎛️ **Modular Toolbar** — Pick exactly which tools appear and in what order
|
|
103
104
|
- 🟦 **TypeScript Ready** — Definitions ship with the package. Options, toolbar entries and variable shapes are all checked, so a mistyped tool name is a compile error rather than a silently missing button
|
|
104
105
|
- 📦 **Universal Module Support** — ESM, CommonJS, UMD, and IIFE. Works with Vite, webpack, Rollup, or directly via `<script src>` CDN — no configuration needed
|
|
105
|
-
- 🚀 **High Performance** — ~
|
|
106
|
+
- 🚀 **High Performance** — ~54KB gzipped (253KB minified). Debounced preview, cached layout calculations, conflict-free Tab/Enter handling for large documents
|
|
106
107
|
|
|
107
108
|
## 🛠 Developer Workflow
|
|
108
109
|
|
|
@@ -140,6 +141,46 @@ const editor = new MarkdownEditor('#markdown-editor', {
|
|
|
140
141
|
});
|
|
141
142
|
```
|
|
142
143
|
|
|
144
|
+
### Add your own toolbar button
|
|
145
|
+
|
|
146
|
+
Most tools are just a title, an icon and a function. No class, no fork:
|
|
147
|
+
|
|
148
|
+
```javascript
|
|
149
|
+
new MarkdownEditor('#markdown-editor', {
|
|
150
|
+
toolbar: ['bold', 'italic', {
|
|
151
|
+
custom: {
|
|
152
|
+
title: 'Callout', // tooltip, and the .callout-btn class
|
|
153
|
+
icon: '<svg>…</svg>',
|
|
154
|
+
shortcut: 'Ctrl+Shift+C', // optional, shown in the tooltip
|
|
155
|
+
action(editor) {
|
|
156
|
+
editor.insertText('> [!NOTE]\n> ');
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}, 'preview']
|
|
160
|
+
});
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Use `editor.insertText(text, caretOffset, trailingLength)` rather than writing to the textarea yourself — it replaces the selection, restores focus, moves the caret, re-renders the preview, fires `onChange`, and keeps undo working.
|
|
164
|
+
|
|
165
|
+
A tool that builds its own markup, such as a dropdown or a dialog, extends the base class instead:
|
|
166
|
+
|
|
167
|
+
```javascript
|
|
168
|
+
class EmbedTool extends MarkdownEditor.Tool {
|
|
169
|
+
constructor(editor) {
|
|
170
|
+
super(editor, 'Embed video');
|
|
171
|
+
this.button = this.createButton('<svg>…</svg>');
|
|
172
|
+
}
|
|
173
|
+
applySyntax(event) {
|
|
174
|
+
// MarkdownEditor.modal is the same dialog the link and image tools use
|
|
175
|
+
const dialog = MarkdownEditor.modal(event, 'fj:max-w-sm', '…', 'Embed');
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
new MarkdownEditor('#markdown-editor', { toolbar: ['bold', EmbedTool, 'preview'] });
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Two helpers exist for tools that need them: `editor.renderMarkdown(md)` returns sanitized HTML exactly as the preview does, and `editor.createToolbar(textarea, ['bold', 'italic'])` builds a real toolbar bound to another textarea, for a tool collecting rich text in its own dialog.
|
|
183
|
+
|
|
143
184
|
### Tear down in SPAs
|
|
144
185
|
|
|
145
186
|
```javascript
|
|
@@ -150,8 +191,15 @@ editor.destroy();
|
|
|
150
191
|
In React, create the editor in an effect and return `destroy` as the cleanup — that also covers StrictMode running effects twice in development:
|
|
151
192
|
|
|
152
193
|
```jsx
|
|
194
|
+
// Options are read once, so reach the latest onChange through a ref rather
|
|
195
|
+
// than rebuilding the editor whenever the parent re-renders
|
|
196
|
+
const onChangeRef = useRef(onChange);
|
|
197
|
+
onChangeRef.current = onChange;
|
|
198
|
+
|
|
153
199
|
useEffect(() => {
|
|
154
|
-
const editor = new MarkdownEditor(ref.current, {
|
|
200
|
+
const editor = new MarkdownEditor(ref.current, {
|
|
201
|
+
onChange: (value) => onChangeRef.current?.(value),
|
|
202
|
+
});
|
|
155
203
|
return () => editor.destroy();
|
|
156
204
|
}, []);
|
|
157
205
|
```
|